﻿using System;
using System.IO;
using System.Collections.Generic;

namespace Game.Lib.CSG
{
    public class Line : Shape1D
    {
        public Vector2 Point { get; set; }

        public float Theta
        {
            get
            {
                return _Theta;
            }
            set
            {
                _Theta = value;
                _Slope = (float)Math.Tan(value);
            }
        }

        public float Slope
        {
            get
            {
                return _Slope;
            }
            set
            {
                _Slope = value;
                _Theta = (float)Math.Atan(value);
            }
        }

        public override List<Vector> CriticalPoints
        {
            get
            {
                List<Vector> ret = new List<Vector>(1);
                ret.Add(Point);
                return ret;
            }
        }

        private float _Slope;
        private float _Theta;

        public override float Length
        {
            get { return float.PositiveInfinity; }
        }

        public Line()
        {
            Point = Vector2.Zero;
            Slope = 0f;
        }

        public Line(Vector2 p, float s)
        {
            Point = p;
            Slope = s;
        }

        public static Vector2 Intersection(Line a, Line b)
        {
            //y=s(x-x0)+y0
            //a.s(x-a.x0)+a.y0 = b.s(x-b.x0)+b.y0
            //a.s * x - a.s * a.x0 + a.y0 = b.s * x - b.s * b.x0 + b.y0
            //a.s * x - b.s * x = a.s * a.x0 -a.y0 - b.s * b.x0 + b.y0
            //Yup
            float top = a.Slope * a.Point.X + b.Point.Y - a.Point.Y - b.Slope * b.Point.X;
            float bottom = a.Slope - b.Slope;
            float x = top / bottom;
            float y = a.Slope * (x - a.Point.X) + a.Point.Y;
            return new Vector2(x, y);
        }
        
        public Vector2 Get(float t)
        {
            return Point + Vector2.FromPolar(t, Theta);
        }

        public override void Serialize(Stream s)
        {
            Point.Serialize(s);
            s.Write(BitConverter.GetBytes(Slope), 0, 4);
        }

        public override void Deserialize(Stream s)
        {
            Point.Deserialize(s);
            byte[] buf = new byte[4];
            if (s.Read(buf, 0, 4) != 4) throw new EndOfStreamException();
            Slope = BitConverter.ToSingle(buf, 0);
        }
    }
}
